﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kaskelot.SP.Core;
using Stockholm.SOA.Kaskelot.WCF.DataContracts;
using Stockholm.SOA.Kaskelot.WCF.ServiceContracts;
using System.ServiceModel;
using Stockholm.SOA.Kaskelot.WCF.FaultContracts;

namespace Kaskelot.SP.Services
{
	public class BemanningService : BaseService<IKaskelotService>
	{
		#region Funktioner
		public Funktion[] GetFunktioner()
		{
			Funktion[] result = null;
			try
			{
				result = this.channel.GetFunktioner(ApplicationContext.Current.Val.Id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetFunktioner", "Error getting funktioner", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}

		public Funktion GetFunktion(Guid id)
		{
			Funktion result = null;
			try
			{
				result = this.channel.GetFunktion(ApplicationContext.Current.Val.Id, id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetFunktion", "Error getting funktion", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}
		#endregion

		#region Bemanna
		public IEnumerable<PersonSearchResult> BemanningSearchPersoner(PersonSearchParameters parameters)
		{
			IEnumerable<PersonSearchResult> result = null;
			try
			{
				result = this.channel.BemanningSearchPersoner(ApplicationContext.Current.Val.Id, parameters);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "SearchPersoner", "Error searching personer", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}

			return result;
		}

		public void BemannaVakans(Guid vakansId, Guid personId, bool removeExisting)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.BemannaVakans(ApplicationContext.Current.Val.Id, vakansId, personId, removeExisting);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "BemannaVakans", "Error bemanna vakans", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
		}
		#endregion

		#region Sökningar
		public IEnumerable<VakansSearchResult> VakansSearch(VakansSearchParameters vsp)
		{
			IEnumerable<VakansSearchResult> result = null;
			try
			{
				result = this.channel.VakansSearch(ApplicationContext.Current.Val.Id, vsp);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "VakansSearch", "Error searching vakans", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}

		public IEnumerable<ValdistriktSearchResult> ValdistriktSearch(ValdistriktSearchParameters vsp)
		{
			IEnumerable<ValdistriktSearchResult> result = null;
			try
			{
				result = this.channel.ValdistriktSearch(ApplicationContext.Current.Val.Id, vsp);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "ValdistriktSearch", "Error searching valdistrikt", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}

		public IEnumerable<Grupp> GruppSearch(Guid? kursTillfalleId)
		{
			IEnumerable<Grupp> result = null;
			try
			{
				result = this.channel.GruppSearch(ApplicationContext.Current.Val.Id, kursTillfalleId);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GruppSearch", "Error searching grupp", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}
		#endregion

		#region Valdistrikt
		public BemanningValdistrikt GetBemanningValdistrikt(Guid id)
		{
			BemanningValdistrikt result = null;
			try
			{
				result = this.channel.GetBemanningValdistrikt(ApplicationContext.Current.Val.Id, id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetBemanningValdistrikt", "Error getting bemanningvaldistrikt", ex);
			}
			return result;
		}

		public void UpdateBemanningValdistrikt(BemanningValdistrikt bg)
		{
			base.CheckWriteAllowed();

			try
			{
				this.channel.UpdateBemanningValdistrikt(bg);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "UpdateBemanningValdistrikt", "Error updating bemanningValdistrikt", ex);
			}
		}

		public ValdistriktDetailsView GetValdistriktDetails(Guid id)
		{
			ValdistriktDetailsView result = null;
			try
			{
				result = this.channel.GetValdistriktDetails(ApplicationContext.Current.Val.Id, id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetValdistriktDetails", "Error getting valdistrikt details", ex);
			}
			return result;
		}

		public void RemovePersonFromBemanningValdistrikt(Guid bemanningId)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.RemovePersonFromBemanningValdistrikt(ApplicationContext.Current.Val.Id, bemanningId);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "RemovePersonFromBemanningValdistrikt", "Error removing person", ex);
			}
		}

		public void DeleteBemanningValdistrikt(Guid bemanningId)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.DeleteBemanningValdistrikt(ApplicationContext.Current.Val.Id, bemanningId);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "DeleteBemanningValdistrikt", "Error deleting BemanningValdistrikt", ex);
			}
		}

		public void CreateBemanningValdistrikt(BemanningValdistrikt bv)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.CreateBemanningValdistrikt(bv);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "CreateBemanningValdistrikt", "Error creating BemanningValdistrikt", ex);
			}
		}
		#endregion

		#region Grupp
		public BemanningGrupp GetBemanningGrupp(Guid id)
		{
			BemanningGrupp result = null;
			try
			{
				result = this.channel.GetBemanningGrupp(ApplicationContext.Current.Val.Id, id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetBemanningGrupp", "Error getting bemanningGrupp", ex);
			}
			return result;
		}

		public void UpdateBemanningGrupp(BemanningGrupp bg)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.UpdateBemanningGrupp(bg);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "UpdateBemanningGrupp", "Error updating bemanningGrupp", ex);
			}
		}

		public GruppDetailsView GetGruppDetails(Guid id)
		{
			GruppDetailsView result = null;
			try
			{
				result = this.channel.GetGruppDetails(ApplicationContext.Current.Val.Id, id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetGruppDetails", "Error getting grupp details", ex);
			}
			return result;
		}

		public void RemovePersonFromBemanningGrupp(Guid bemanningId)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.RemovePersonFromBemanningGrupp(ApplicationContext.Current.Val.Id, bemanningId);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "RemovePersonFromBemanningGrupp", "Error removing person", ex);
			}
		}

		public void DeleteBemanningGrupp(Guid bemanningId)
		{
			base.CheckWriteAllowed();
			try
			{
				this.channel.DeleteBemanningGrupp(ApplicationContext.Current.Val.Id, bemanningId);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "DeleteBemanningGrupp", "Error deleting BemanningGrupp", ex);
			}
		}

		public void CreateBemanningGrupp(BemanningGrupp bv)
		{
			base.CheckWriteAllowed();

			try
			{
				this.channel.CreateBemanningGrupp(bv);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "CreateBemanningGrupp", "Error creating BemanningGrupp", ex);
			}
		}
		#endregion

		public IEnumerable<BemanningGrupp> GetBemanningGruppByPersonId(Guid id)
		{
			IEnumerable<BemanningGrupp> result = null;
			try
			{
				result = this.channel.GetBemanningGruppByPersonId(id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetBemanningGruppByPersonId", "Error getting bemanninggrupp by personid", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}

		public IEnumerable<BemanningValdistrikt> GetBemanningValdistriktByPersonId(Guid id)
		{
			IEnumerable<BemanningValdistrikt> result = null;
			try
			{
				result = this.channel.GetBemanningValdistriktByPersonId(id);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetBemanningValdistriktByPersonId", "Error getting bemanningvaldistrikt by personid", ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}
			return result;
		}

		public IEnumerable<PersonUppdrag> GetBemanningByPersonId(Guid id)
		{
			var grupper = GetBemanningGruppByPersonId(id);
			var valdistrikt = GetBemanningValdistriktByPersonId(id);

			IList<PersonUppdrag> list = new List<PersonUppdrag>();

			foreach (BemanningGrupp g in grupper)
			{
				list.Add(new PersonUppdrag
				{
					UppdragFunktion = g.FunktionNamn,
					UppdragNamn = g.GruppNamn,
					UppdragVal = g.ValNamn,
					GruppId = g.GruppId.ToString()
				});
			}

			foreach (BemanningValdistrikt v in valdistrikt)
			{
				list.Add(new PersonUppdrag
				{
					UppdragFunktion = v.FunktionNamn,
					UppdragNamn = v.ValdistriktNamn,
					UppdragVal = v.ValNamn,
					ValdistriktId = v.ValdistriktId.ToString()
				});
			}

			return list.OrderByDescending(gubpr => gubpr.UppdragVal).ThenBy(gubpr => gubpr.UppdragNamn);
		}

		public IEnumerable<ValdistriktFull> GetValdistriktFull(IEnumerable<Guid> idList)
		{
			IEnumerable<ValdistriktFull> res = null;

			try
			{
				res = this.channel.GetValdistriktFull(ApplicationContext.Current.Val.Id, idList);
			}
			catch (FaultException<ErrorInformation> ex)
			{
				Logger.LogError(this, LayerNames.Services, "GetValdistriktFull", string.Format("Error getting valdistrikt list"), ex);
                throw new ApplicationException(ex.Detail.ServiceError);
			}

			return res;
		}
	}
}
